package com.demo.crm.controller;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.arvato.crm.common.DynamicQueryUtil;
import com.arvato.crm.model.entity.Manager;
import com.arvato.crm.model.entity.Permission;
import com.arvato.crm.model.entity.Role;
import com.demo.crm.model.ButtonInfo;
import com.demo.crm.model.RequestInfo;
import com.demo.crm.model.UserToken;
import com.demo.crm.security.access.provider.ProviderByUrl;
import com.demo.crm.security.filter.AccessFilter;

/**
 * @author tanshuai
 */
@Controller
@RequestMapping("/permission")
public class PermissionController {

    @Autowired
    private AccessFilter accessFilter;

    @RequestMapping("/all")
    @ResponseBody
    public List<Permission> all() {
        return DynamicQueryUtil.getCriteria(Permission.class).orderByAsc("ordered").getResultList();
    }
    
    @RequestMapping("/menus")
    @ResponseBody
    public List<Permission> menus(Manager manager) {
        return getMenusByManager(manager.getId());
    }

    private List<Permission> getMenusByManager(String managerId) {
    	List<Role> roles = DynamicQueryUtil.getCriteria(Role.class).innerJoin("managers").andEquals("managers.id", managerId).getResultList();
    	// 去重
        Set<Permission> perms = new LinkedHashSet<Permission>();
        for (Role role : roles) {
        	perms.addAll(role.getPermissions());
        }

        List<Permission> list=new ArrayList<Permission>(perms);
        Collections.sort(list, new Comparator<Permission>() {
            @Override
            public int compare(Permission o1, Permission o2) {
                if (o1.getParentId()==o2.getParentId()){
                    return o1.getOrdered()-o2.getOrdered();
                }

                return 0;
            }
        });

        return list;
	}
    
	/**
     * 刷新权限缓存
     */
    @RequestMapping("/refresh")
    @ResponseBody
    public void refresh() {
        ProviderByUrl.loadCaches();
    }

    /**
     * 校验该按钮或链接是否需要禁用
     *
     * @param buttonInfoList 页面上的按钮列表
     * @param request        请求信息，用来获取当前用户信息
     * @return 校验后的列表
     */
    @RequestMapping("/ignore/valid")
    @ResponseBody
    public List<ButtonInfo> validation(@RequestBody List<ButtonInfo> buttonInfoList, HttpServletRequest request) {
        UserToken userToken = UserToken.getUserToken(request);
        for (ButtonInfo buttonInfo : buttonInfoList) {
            RequestInfo requestInfo = new RequestInfo(buttonInfo.getUrl());
            buttonInfo.setDisable(!accessFilter.couldAccess(requestInfo, userToken));
        }
        return buttonInfoList;
    }

    private List<Map> getChildren(String parentId, List<Permission> permissions) {
        List<Map> children = new ArrayList<>();
        for (Permission permission : permissions) {
            if (permission.getParentId().equals(parentId)) {
                Map map = new HashMap();
                map.put("id", permission.getId());
                map.put("text", permission.getName());

                Map attributes = new HashMap();
                attributes.put("path", permission.getPath());
                attributes.put("type", permission.getType().getValue());
                attributes.put("ordered", permission.getOrdered());

                map.put("attributes", attributes);
                map.put("children", getChildren(String.valueOf(permission.getId()), permissions));
                children.add(map);
            }
        }

        return children;
    }
}
